package auth

import (
	"gin-demo/core"
	"gin-demo/sysinit"
	"log"
	"time"

	jwt "github.com/appleboy/gin-jwt/v2"
	"github.com/gin-gonic/gin"
)

// JWT 中间件全局变量
var JWT *jwt.GinJWTMiddleware

// InitJWT 初始化JWT中间件
func InitJWT() {
	var identityKey = "id"
	var err error
	JWT, err = jwt.New(&jwt.GinJWTMiddleware{
		Realm:       "test zone",
		Key:         []byte(sysinit.Config.GetString("app.secret_key")),
		Timeout:     time.Hour,
		MaxRefresh:  time.Hour * 24,
		IdentityKey: identityKey,
		PayloadFunc: func(data interface{}) jwt.MapClaims {
			if v, ok := data.(*User); ok {
				return jwt.MapClaims{
					identityKey: v.ID,
					"username":  v.Username,
				}
			}
			return jwt.MapClaims{}
		},
		IdentityHandler: func(ctx *gin.Context) interface{} {
			claims := jwt.ExtractClaims(ctx)
			user := User{}
			if id, ok := claims[identityKey].(float64); ok {
				user.ID = uint(id)
			}
			return &user
		},
		Authenticator: func(ctx *gin.Context) (interface{}, error) {
			var loginForm UserLoginForm
			var service UserService
			if err := ctx.ShouldBindJSON(&loginForm); err != nil {
				// return "", jwt.ErrMissingLoginValues
				return "", err
			}
			if user, ok := service.GetByUsername(loginForm.Username); ok {
				if core.VerifyPassword(user.Password, loginForm.Password) == nil {
					return &user, nil
				}
			}
			return nil, jwt.ErrFailedAuthentication
		},
		Authorizator: func(data interface{}, c *gin.Context) bool {
			if v, ok := data.(*User); ok {
				return v.ID > 0
			}
			return false
		},
		Unauthorized: func(c *gin.Context, code int, message string) {
			c.JSON(code, gin.H{
				"code":    code,
				"message": message,
			})
		},
		TokenLookup:   "header: Authorization, query: token, cookie: jwt",
		TokenHeadName: "Bearer",
		TimeFunc:      time.Now,
	})
	if err != nil {
		log.Fatal(err)
	}
}
